/**
  ************************************* Copyright ******************************
  * FileName   : my_protocol.c
  * Version    : v1.0
  * Author     : yychao
  * Date       : 2024-02-18
  * Description:
  * Function List:
  	1. ....
  	   <version>:
  <modify staff>:
  		  <data>:
   <description>:
  	2. ...
  ******************************************************************************
 */

#include "log.h"
#include "usart.h"
#include "string.h"
#include "my_protocol.h"

uint8_t trans_cache[128];

struct pro_data pro_data_trans_st = {0x00};
struct pro_data pro_data_pre_st = {0x00};	//preprocess
struct pro_data pro_data_recv_st = {0x00};	//
struct pro_number pro_recv;
struct pro_number pro_trans;

uint8_t sum_check(uint8_t *data, uint8_t len)
{
    uint8_t val = 0;
    for(uint8_t i = 0; i < len; i++) {
        val += data[i];
    }
    return val;

}
void cnn_485_deal(usart_cache* recv) //DataBuff* recv
{
    protocol_adv(&recv->data[3], recv->cnt - 3);
}
void protocol_adv(uint8_t *data, uint16_t len)
{
    uint8_t cache[128] = { 0x00 };
    if ((len) != data[1]) {
#if 0
        for (uint16_t j = 0; j < len; j++) {
            LOG_ERROR("%x ", data[j]);
        }
        LOG_ERROR("\r\n");
        LOG_ERROR("Stick the data package!\r\n");
#endif
        for (uint16_t i = 0; i < len;) {
            if (data[i] == S2M_HEAD) {
                memset(&cache[0], 0x00, 128);
                memcpy(&cache[0], &data[i], data[i + 1]);
                my_protocol(&cache[0], data[i + 1]);
                i = i + data[i + 1];
            } else {
                i++;
            }
        }
    } else {
        my_protocol(&data[0], len);
    }
}
void my_protocol(uint8_t *data, uint16_t cnt)
{

    pro_recv.head = data[0];
    if(pro_recv.head != S2M_HEAD) {
        LOG_ERROR("ERR_HEAD\r\n");
        for (uint16_t j = 0; j < cnt; j++) {
            LOG_ERROR("%x ", data[j]);
        }
        goto pro_err;
    }

    pro_recv.all_len = data[1];
    if((pro_recv.all_len != cnt)||(pro_recv.all_len < 7)) {
        LOG_ERROR("ERR_ALL_LEN\r\n");
        for (uint16_t j = 0; j < cnt; j++) {
            LOG_ERROR("%x ", data[j]);
        }
        goto pro_err;
    }

    pro_recv.crc = data[cnt - 1];
    if(pro_recv.crc != sum_check(&data[0], cnt - 1)) {
        LOG_ERROR("ERR_CRC\r\n");
        goto pro_err;
    }

    pro_recv.reg_start = data[4];
    pro_recv.reg_num = data[5];

    pro_recv.operate = data[2];
    pro_recv.reg_type = data[3];
    switch(pro_recv.operate) {
    case OP_RES_READ:
        op_res_read(&data[0], cnt);
        break;
    case OP_RES_WRITE:
        op_res_write(&data[0], cnt);
        break;
    default:
        LOG_ERROR("ERR_OPERATE\r\n");
        goto pro_err;
        break;
    }
pro_err:
    NULL;
}

void op_res_read(uint8_t *data, uint8_t len)
{

    switch(pro_recv.reg_type) {
    case REG_COIL:

        for(uint8_t i = 0; i < pro_recv.reg_num; i++) {
            pro_data_recv_st.coil[pro_recv.reg_start + i] = data[6 + i];
        }
        break;
    case REG_DIS:
        for(uint8_t i = 0; i < pro_recv.reg_num; i++) {
            pro_data_recv_st.dis[pro_recv.reg_start + i] = data[6 + i];
        }
        break;
    case REG_HOLD:
        for(uint8_t i = 0; i < pro_recv.reg_num; i++) {
            pro_data_recv_st.hold[pro_recv.reg_start + i] = data[6 + i*2];
            pro_data_recv_st.hold[pro_recv.reg_start + i] = pro_data_trans_st.hold[pro_recv.reg_start + i]<<8;
            pro_data_recv_st.hold[pro_recv.reg_start + i] |= data[6 + i*2 + 1] ;
        }
        break;
    case REG_INPUT:
        for(uint8_t i = 0; i < pro_recv.reg_num; i++) {
            pro_data_recv_st.input[pro_recv.reg_start + i] = data[6 + i*2];
            pro_data_recv_st.input[pro_recv.reg_start + i] = pro_data_trans_st.input[pro_recv.reg_start + i]<<8;
            pro_data_recv_st.input[pro_recv.reg_start + i] |= data[6 + i*2 + 1];
        }
        break;
    default:
        LOG_ERROR("ERR_REG_TYPE1\r\n");
        break;
    }

    pro_trans.cnn_status = CNN_FINISHED;
}
void op_res_write(uint8_t *data, uint8_t len)
{
    pro_trans.cnn_status = CNN_FINISHED;
}

void read(uint8_t reg_type, uint8_t reg_start, uint8_t reg_num)
{
    uint32_t tim_cnt = 0;
    pro_trans.cnn_status = CNN_NONE;
    pro_trans.head = M2S_HEAD;
    pro_trans.all_len = 7;
    pro_trans.operate = OP_READ;
    pro_trans.reg_type = reg_type;
    pro_trans.reg_start = reg_start;
    pro_trans.reg_num = reg_num;

    trans_cache[0] = pro_trans.head;
    trans_cache[1] = pro_trans.all_len;
    trans_cache[2] = pro_trans.operate;
    trans_cache[3] = pro_trans.reg_type;
    trans_cache[4] = pro_trans.reg_start;
    trans_cache[5] = pro_trans.reg_num;
    trans_cache[6] = sum_check(&trans_cache[0], trans_cache[1] - 1);
    usart_485trans(CNN_485, &trans_cache[0], pro_trans.all_len);
    pro_trans.cnn_status = CNN_WAIT;
    tim_cnt = 0;
    while(pro_trans.cnn_status != CNN_FINISHED) {
        if(tim_cnt >= 500) {
            pro_trans.cnn_status = CNN_OVERTIME;
            break;
        }
        tim_cnt++;
        rt_thread_delay(1);
    }
    if(pro_trans.cnn_status != CNN_FINISHED) {
        LOG_INFO("read cnn_status %d\r\n", pro_trans.cnn_status);
    }
}

void write(uint8_t reg_type, uint8_t reg_start, uint8_t reg_num, uint16_t* data)
{

    uint32_t tim_cnt = 0;
    pro_trans.cnn_status = CNN_NONE;

    pro_trans.head = M2S_HEAD;
    pro_trans.operate = OP_WRITE;
    pro_trans.reg_type = reg_type;
    pro_trans.reg_start = reg_start;
    pro_trans.reg_num = reg_num;


    trans_cache[0] = pro_trans.head;
    trans_cache[2] = pro_trans.operate;
    trans_cache[3] = pro_trans.reg_type;
    trans_cache[4] = pro_trans.reg_start;
    trans_cache[5] = pro_trans.reg_num;
    switch(pro_trans.reg_type) {
    case REG_COIL:
        pro_trans.all_len = 7 + pro_trans.reg_num;
        trans_cache[1] = pro_trans.all_len;
        for(uint8_t i = 0; i < pro_trans.reg_num; i++) {
            trans_cache[6 + i] = data[i];
        }
        trans_cache[6 + pro_trans.reg_num] = sum_check(&trans_cache[0], trans_cache[1] - 1);
        usart_485trans(CNN_485, &trans_cache[0], pro_trans.all_len);
        break;
    case REG_HOLD:
        pro_trans.all_len = 7 + pro_trans.reg_num*2;
        trans_cache[1] = pro_trans.all_len;
        for(uint8_t i = 0; i < pro_trans.reg_num; i++) {
            trans_cache[6 + i*2] = data[i] >> 8;
            trans_cache[6 + i*2 + 1] = data[i];
        }
        trans_cache[6 + pro_trans.reg_num*2] = sum_check(&trans_cache[0], trans_cache[1] - 1);
        usart_485trans(CNN_485, &trans_cache[0], pro_trans.all_len);
        break;
    default:
        LOG_ERROR("ERR_REG_TYPE1\r\n");
        break;
    }

    pro_trans.cnn_status = CNN_WAIT;
    while(pro_trans.cnn_status != CNN_FINISHED) {
        if(tim_cnt >= 100) {
            pro_trans.cnn_status = CNN_OVERTIME;
            break;
        }
        tim_cnt++;
        rt_thread_delay(5);
    }
    if(pro_trans.cnn_status != CNN_FINISHED) {
        LOG_INFO("write cnn_status %d\r\n", pro_trans.cnn_status);
    }
}

